#!/usr/bin/env python
# $Id: ipverify.py df54dec975f4 2012/09/09 20:22:40 pgurumur $
# Copyright (c) 2012 Prabhu Gurumurthy <pgurumur@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

__version__  = "$Revision: df54dec975f4 $"
__author__   = "$Author: pgurumur $"
__modified__ = "$Date: 2012-09-09 20:22:40Z $"

import datetime
import os
import optparse
import signal
import sys
import time

from sqlalchemy import Column, Integer, String, Numeric, Unicode
from sqlalchemy.orm import mapper
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import *
 
from venya.lib import cmdparser
from venya.lib import ip
from venya.lib import log
from venya.lib import sql
from venya.lib import stdlib

class ModelError(Exception):
   pass

Base = declarative_base()
class DeviceIP(Base):
   __tablename__ = u'ip_verify'

   pk = Column(Integer, primary_key = True)
   device = Column(Unicode(75), nullable = False)
   devid = Column(Integer, nullable = False)
   devip = Column(Integer, nullable = False)
   ipaddr = Column(Numeric(40, 0), nullable = False)
   ipprefix = Column(Integer, nullable = False)
   ipver = Column(Integer, nullable = False)
   ipparent = Column(Integer, nullable = False)
   ipdesc = Column(Unicode(75), nullable = True)
   lastupdate = Column(Numeric(11, 7), nullable = False)

   def __init__(self, **Keywords):
      super(DeviceIP, self).__init__()
      if "device" in Keywords:
         self.device = Keywords["device"]

      if "devid" in Keywords:
         self.devid = self.GetInteger(Keywords["devid"])

      if "devip" in Keywords:
         self.devip = self.GetInteger(Keywords["devip"])

      if "ipaddr" in Keywords:
         self.ipaddr = Keywords["ipaddr"]

      if "parent" in Keywords:
         self.ipparent = self.GetInteger(Keywords["parent"])

      if "prefix" in Keywords:
         self.ipprefix = self.GetInteger(Keywords["prefix"])

      if "version" in Keywords:
         self.ipver = self.GetInteger(Keywords["version"])

      if "descr" in Keywords:
         self.ipdesc = self.GetInteger(Keywords["descr"])

      self.lastupdate = time.time()

   def __str__(self):
      return str(self.device)

   @property
   def update(self):
      return datetime.date.fromtimestamp(self.lastupdate)

   def GetInteger(self, Object):
      retval = 0
      try:
         retval = int(Object)
      except ValueError as err:
         raise ModelError(err.message)

      return retval

class ipverify(cmdparser.GetOpt):
   option_list = (
         optparse.make_option("-u", "--update", action = "store_true",
            help = "Update verify database", default = False, dest = "update"),
         optparse.make_option("-r", "--remove", action = "store_true",
            help = "Remove device from database", default = False,
            dest = "remove"),
         optparse.make_option("-a", "--add", action = "store_true",
            help = "Add device to database", default = False,
            dest = "add"),
         optparse.make_option("-d", "--database", type = "str",
            help = "SQLite database, default: neteng.db",
            default = "neteng.db", dest = "db"),
         optparse.make_option("-c", "--config", type = "str",
            help = "Configuration db for MySQL database credentials",
            default = "config.db", dest = "config"),
         optparse.make_option("-l", "--list", action = "store_true",
            help = "List the information in verify databse", default = False,
            dest = "dblist"),
         ) + cmdparser.GetOpt.option_list

   def __init__(self, **keywords):
      super(self.__class__, self).__init__(**keywords)
      self._log = log.StreamLog(stdlib.my_name(self))
      self._host = None
      self._neteng = None
      self._netdot = None
      self._verify = None

   def create(self, engine):
      if engine:
         try:
            Base.metadata.create_all(engine)
         except OpertionalError as err:
            self.error(err.message)
      else:
         self.error("no engine defined!")

   def handle(self):
      (options, args) = self.parse()
      try:
         self._host = args[1]
      except IndexError as err:
         pass

      if options.db:
         self._neteng = sql.sqlite(options.db, bool(options.verbosity))

         try:
            self.create(self._neteng.engine)
         except sql.SQLError as err:
            self.error(err.message)

         self._verify = self._neteng.ip_verify
         print(self._verify)

      self._netdot = sql.mysql("netdot",
            "sirius", "djanet", "oS9XckUcTAHc5rjlcPt1")
      device = self._netdot.device
      ipblock = self._netdot.ipblock
      rr = self._netdot.rr
      zone = self._netdot.zone

      if options.update:
         flag = True
         for ix in device.q.values(device.id, device.name, device.snmp_target):
            (devid, temp, ipid) = ix
            if temp and flag:
               [(zid, devname) for (zid, devname) in rr.q.filter(
                  rr.id == temp).values(rr.zone, rr.name)]
               [name for name in zone.q.filter(
                  zone.id == zid).values(zone.name)]
               devname = "%s.%s" %(devname, name[0])
            else:
               self.log("device with id %d does not have name defined", devid)
               flag = False

            if ipid and flag:
               [(ipaddr, prefix, version, parent, descr) for (ipaddr, prefix,
                  version, parent, descr) in ipblock.q.filter(
               ipblock.id == ipid).values(ipblock.address, ipblock.prefix,
                  ipblock.version, ipblock.parent, ipblock.description)]

               query = self._verify.q.filter(self._verify.devid == devid)
               count = query.count()
               if count == 0:
                  print("adding %s" %devname)
                  table = DeviceIP(device = devname, devid = devid,
                        devip = ipid, ipaddr = ipaddr, parent = parent,
                        prefix = prefix, version = version)
                  self._neteng.add(table, commit = True)
               else:
                  print(query.value(self._verify.pk))
            else:
               self.log("device %s does not have ip defined!", devname)
               flag = False

      if options.dblist:
         for ix in self._verify.q.all():
            print(ix)

if __name__ == "__main__":
   verify = None
   try:
      verify = ipverify(version = 1.0, args = sys.argv, usage = "[ device ip ]")
      if len(verify) <= 1:
         verify.printhelp()
      else:
         verify.handle()
   except cmdparser.GetOptError as err:
      print(err.message)
      sys.exit(1)
